/*
 * BetaModelThermistor.cpp
 *
 * Copyright 2012 Pieter Agten
 *
 * This file is part of tltgen.
 *
 * tltgen is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * tltgen is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with tltgen.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @file   BetaModelThermistor.cpp
 * @author Pieter Agten (pieter.agten@gmail.com)
 * @date   2 sep 2012
 */


#include <boost/lexical_cast.hpp>
#include <cmath>
#include <stdexcept>

#include "ThermistorVisitor.hpp"

#include "BetaModelThermistor.hpp"

namespace tltgen  {

  BetaModelThermistor::BetaModelThermistor(Temperature t0, Resistance r0, double beta) :
    t0(t0), r0(r0), beta(beta)
  {
    if (! isValidT0(t0)) {
      throw std::invalid_argument("Value '" + boost::lexical_cast<std::string>(t0) + "' is invalid for parameter T0.");
    }
    if (! isValidR0(r0)) {
      throw std::invalid_argument("Value '" + boost::lexical_cast<std::string>(r0) + "' is invalid for parameter R0.");
    }
    if (! isValidBeta(beta)) {
      throw std::invalid_argument("Value '" + boost::lexical_cast<std::string>(beta) + "' is invalid for parameter Beta.");
    }
  }

  BetaModelThermistor::~BetaModelThermistor() { };

  bool BetaModelThermistor::isValidT0(Temperature t0)
  {
    return tltgen::isValidKelvinTemperature(t0);
  }
  Resistance BetaModelThermistor::getT0(void) const
  {
    return this->t0;
  }


  bool BetaModelThermistor::isValidR0(Resistance r0)
  {
    return tltgen::isValidResistance(r0);
  }
  Resistance BetaModelThermistor::getR0(void) const
  {
    return this->r0;
  }

  bool BetaModelThermistor::isValidBeta(double beta)
  {
    return beta > 0;
  }
  double BetaModelThermistor::getBeta(void) const
  {
    return this->beta;
  }

  bool BetaModelThermistor::isValidParameterIndex(unsigned int pi) const
  {
    return 0 <= pi && pi < 3;
  }

  double BetaModelThermistor::getParameterValue(unsigned int pi) const
  {
    if (! isValidParameterIndex(pi)) {
      throw std::invalid_argument("The given parameter index is invalid.");
    }

    switch (pi) {
    case 0:
      return getT0();
    case 1:
      return getR0();
    case 2:
      return getBeta();
    default:
      throw std::runtime_error("Default switch case should not be reachable.");
    }
  }

  bool BetaModelThermistor::isValidResistance(Resistance r) const
  {
    return tltgen::isValidResistance(r);
  }
  Temperature BetaModelThermistor::getTemperature(Resistance r) const
  {
    Temperature T0 = getT0();
    Resistance R0 = getR0();
    double B = getBeta();
  
    Resistance Rinf = R0 * exp(-B/T0);
    double T = B / log(r/Rinf);
    return T;
  }


  bool BetaModelThermistor::isValidTemperature(Temperature t) const
  {
    return tltgen::isValidKelvinTemperature(t) && t >= 0;
  }
  Resistance BetaModelThermistor::getResistance(Temperature t) const
  {
    Temperature T0 = getT0();
    Resistance R0 = getR0();
    double B = getBeta();

    Resistance Rinf = R0 * exp(-B/T0);
    Resistance R = Rinf * exp(B/t);
    return R;
  }

  void BetaModelThermistor::accept(ThermistorVisitor* visitor) const
  {
    visitor->visit(this);
  }

  std::ostream &BetaModelThermistor::print(std::ostream &stream) const
  {
    return stream << "Thermistor with beta parameters: " <<
      "T0=" << boost::lexical_cast<std::string>(getT0()) << "K " <<
      "R0=" << boost::lexical_cast<std::string>(getR0()) << "Ohm " <<
      "Beta=" << boost::lexical_cast<std::string>(getBeta());
  }

}

